import UIBase from "./UIBase";
import LayerMgr from "./LayerMgr";
import AppConst from "../AppConst";
import mi from "../MI";


class UIOpen {
    constructor(public uiCls: string, public args: any[]) {
    }
}


export default class UIMgr {
    private static _uis: { [uiName: string]: UIBase; } = {};
    private static _current: UIBase = null;
    // UI 打开记录
    private static _uiOpens: UIOpen[] = [];


    /**
     * 打开 UI
     * @param uiCls UI 类
     * @param uiCallback UI 打开成功回调
     * @param uiArgs UI 参数
     * @returns 
     */
    public static open(uiCls: any, uiCallback?: Function, ...uiArgs: any[]): void {
        if (this._current && this._current.uiName == uiCls) {
            cc.error('试图切换场景至当前UI:%s', uiCls);
            return;
        }

        // 进入主 UI，把 UI 打开记录清空
        if (mi.uiMain == uiCls.name) this._uiOpens = [];
        this._uiOpens.push(new UIOpen(uiCls, uiArgs));

        this.hideCurrentUI();
        this.show(uiCls, (err: any) => {
            if (!err) {
                if (uiCallback) uiCallback();
            } else {
                cc.log('切换UI失败, uiName:%s, err:%s', uiCls, err);
            }
        }, uiArgs);
    }

    /**
     * 打开上一个 UI
     * @param uiCallback UI 打开成功回调
     * @returns 
     */
    public static openPrev(uiCallback?: Function): void {
        if (this._uiOpens.length < 2) {
            cc.error('切换至上一个场景时, 没有上一个场景记录, 请检查逻辑');
            return;
        }
        const prev = this._uiOpens[this._uiOpens.length - 2]; //上一个 UI
        this._uiOpens.splice(this._uiOpens.length - 2, 2); //切换至上一个 UI 后, 请除最后一个 UI (即当前UI) 和上一 UI
        this.open(prev.uiCls, uiCallback, prev.args);
    }

    public static isAlive(uiCls: any): boolean {
        return this._current != null && uiCls == this._current.uiName;
    }

    public static updateView(uiCls: any, ...args: any[]): void {
        if (!this.isAlive(uiCls)) {
            cc.error('[%s]更新 view 失败, 不是当前 ui', uiCls.name);
            return;
        }
        this._current.updateView(args);
    }


    private static show(uiCls: any, showCallback: Function, uiArgs: any[]): void {
        if (this._uis[uiCls]) {
            this._current = this._uis[uiCls];
            this._current.reset(uiArgs);
            this._current.showing();
            this._current.skin.active = true;
            LayerMgr.setLayer(this._current.skin, AppConst.viewLayer.UI);
            this._current.showed();
        } else {
            this._current = new uiCls();
            this._uis[uiCls] = this._current;
            this._current.uiName = uiCls;
            this._current.init(uiArgs);

            cc.loader.loadRes(this._current.skinPath, (err, uiPerfab) => {
                if (!err) {
                    const skin = cc.instantiate(uiPerfab);
                    this._current.skin = skin;
                    this._current.initDone();

                    this._current.showing();
                    LayerMgr.setLayer(this._current.skin, AppConst.viewLayer.UI);
                    this._current.showed();
                }
                showCallback(err);
            });
        }
    }

    private static hideCurrentUI(): void {
        if (this._current) {
            this._current.hiding();
            this._current.skin.active = false;
            this._current.hided();

            if (!this._current.cache) {
                delete this._uis[this._current.uiName];
                this._current.destroy();
                this._current = null;
            }
        }
    }
}
